package objectAnalyzer;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;

public class ObjectAnalyzer {
    private ArrayList<Object> visited = new ArrayList<>();

    public String toString(Object obj, int depth) throws ReflectiveOperationException {
        if (obj == null) {
            return "null";
        }

        // 避免递归
        if (visited.contains(obj)) {
            return "...";
        }
        visited.add(obj);

        Class<?> cl = obj.getClass();

        // 对象是字符串，直接输出
        if (cl == String.class) {
            return (String) obj;
        }

        // 对象是数组
        if (cl.isArray()) {
            String r =  cl.getComponentType() + "[] {\n";
            for (int i = 0; i < Array.getLength(obj); i++) {
                if (i > 0) {
                    r += ",\n";
                }
                r += "    ".repeat(depth + 1);

                Object val = Array.get(obj, i);
                // 如果数组元素是基本类型，则直接附加，否则附加递归结果
                if (cl.getComponentType().isPrimitive()) {
                    r += val;
                } else {
                    r += toString(val, depth + 1);
                }
            }
            r += "}";
            return r;
        }

        String r = cl.getName();

        // 递归处理所有字段, 包括超类的字段
        r +=  " [\n";
        for (;cl != null; cl = cl.getSuperclass()) {
            // 获取当前类的所有字段
            Field[] fields = cl.getDeclaredFields();

            // 设置所有字段可访问
            AccessibleObject.setAccessible(fields, true);

            for (Field f : fields) {
                // 如果不是静态字段，则附加字段名及值
                if (!Modifier.isStatic(f.getModifiers())) {
                    // 不是第一个字段，则附加逗号
                    if (!r.endsWith("\n")) {
                        r += ",\n";
                    }
                    r += "    ".repeat(depth + 1);

                    r += f.getName() + " = ";

                    // 如果字段是基本类型，则直接附加值，否则附加递归结果
                    Class<?> t = f.getType();
                    Object val = f.get(obj);
                    if (t.isPrimitive()) {
                        r += val;
                    }
                    else {
                        r += toString(val, depth + 1);
                    }
                }
            }
        }
        r += "]";
        return r;
    }
}

